import os
import math
import chardet

def detect_encoding(file_path):
    """
    检测文件编码
    
    Args:
        file_path (str): 文件路径
        
    Returns:
        str: 检测到的编码格式
    """
    try:
        with open(file_path, 'rb') as f:
            raw_data = f.read(10000)  # 读取前10000字节用于检测
            result = chardet.detect(raw_data)
            encoding = result['encoding']
            
            # 如果chardet无法确定编码，使用默认编码
            if encoding is None:
                return 'utf-8'
            return encoding
    except Exception:
        # 如果检测失败，返回默认编码
        return 'utf-8'

def split_txt_file(input_file_path, max_size_mb=3):
    """
    将指定的txt文件拆分成多个小于max_size_mb大小的文件

    Args:
        input_file_path (str): 输入文件路径
        max_size_mb (int): 每个拆分文件的最大大小(MB)
    """

    # 检查文件是否存在
    if not os.path.exists(input_file_path):
        raise FileNotFoundError(f"文件 {input_file_path} 不存在")

    # 获取文件大小
    file_size = os.path.getsize(input_file_path)
    max_size_bytes = max_size_mb * 1024 * 1024

    # 如果文件本身就不超过限制，则不需要拆分
    if file_size <= max_size_bytes:
        print(f"文件大小 {file_size / (1024*1024):.2f} MB，小于 {max_size_mb} MB，无需拆分")
        return

    # 检测文件编码
    detected_encoding = detect_encoding(input_file_path)
    print(f"检测到文件编码: {detected_encoding}")

    # 尝试使用检测到的编码，如果失败则尝试其他常见编码
    encodings_to_try = [detected_encoding, 'utf-8', 'gbk', 'gb2312', 'latin1']
    encoding = None
    for enc in encodings_to_try:
        try:
            with open(input_file_path, 'r', encoding=enc) as test_file:
                test_file.read(100)  # 尝试读取一小部分
            encoding = enc
            break
        except UnicodeDecodeError:
            continue
    
    if encoding is None:
        raise ValueError("无法确定文件编码格式")

    print(f"使用编码: {encoding}")

    # 创建输出目录
    base_name = os.path.splitext(os.path.basename(input_file_path))[0]
    output_dir = f"{base_name}_split"
    os.makedirs(output_dir, exist_ok=True)

    # 计算需要拆分成多少个文件
    num_files = math.ceil(file_size / max_size_bytes)

    print(f"原始文件大小: {file_size / (1024*1024):.2f} MB")
    print(f"将拆分成 {num_files} 个文件，每个文件最大 {max_size_mb} MB")

    # 逐块读取并写入新文件
    with open(input_file_path, 'r', encoding=encoding, errors='ignore') as input_file:
        file_index = 0
        current_output_file = None
        current_size = 0

        try:
            for line in input_file:
                # 如果当前输出文件为空或者已达到大小限制，则创建新文件
                if current_output_file is None or current_size >= max_size_bytes:
                    if current_output_file:
                        current_output_file.close()

                    file_index += 1
                    output_file_path = os.path.join(output_dir, f"{base_name}_part{file_index}.txt")
                    current_output_file = open(output_file_path, 'w', encoding=encoding)
                    current_size = 0
                    print(f"正在创建文件: {output_file_path}")

                # 写入当前行
                current_output_file.write(line)
                current_size += len(line.encode(encoding, errors='ignore'))

            # 关闭最后一个文件
            if current_output_file:
                current_output_file.close()

        except Exception as e:
            if current_output_file:
                current_output_file.close()
            raise e

    print(f"文件拆分完成！共生成 {file_index} 个文件，存储在目录: {output_dir}")

def select_and_split_file():
    """
    选择本地文件并进行拆分
    """
    try:
        # 在实际应用中，可以使用tkinter来实现文件选择对话框
        # 这里为了简化，我们直接要求输入文件路径
        file_path = input("请输入要拆分的txt文件路径: ").strip()

        # 处理引号包围的路径
        if file_path.startswith('"') and file_path.endswith('"'):
            file_path = file_path[1:-1]
        elif file_path.startswith("'") and file_path.endswith("'"):
            file_path = file_path[1:-1]

        # 拆分文件
        split_txt_file(file_path)

    except KeyboardInterrupt:
        print("\n操作被用户取消")
    except Exception as e:
        print(f"发生错误: {e}")

# 使用tkinter实现图形界面文件选择（可选）
def select_file_gui():
    """
    使用GUI选择文件
    """
    try:
        import tkinter as tk
        from tkinter import filedialog

        root = tk.Tk()
        root.withdraw()  # 隐藏主窗口

        file_path = filedialog.askopenfilename(
            title="选择要拆分的TXT文件",
            filetypes=[("Text files", "*.txt"), ("All files", "*.*")]
        )

        if file_path:
            split_txt_file(file_path)
        else:
            print("未选择文件")

    except ImportError:
        print("tkinter不可用，请直接运行 select_and_split_file()")

if __name__ == "__main__":
    # 运行命令行版本
    select_and_split_file()

    # 或者运行GUI版本（如果需要）
    # select_file_gui()
